package cn.gaozhong.basic.service.impl;

import cn.gaozhong.basic.constart.BaseConstant;
import cn.gaozhong.basic.dto.LoginDto;
import cn.gaozhong.basic.dto.RegisterDto;
import cn.gaozhong.basic.dto.WeChatDto;
import cn.gaozhong.basic.exception.CustomException;
import cn.gaozhong.basic.service.ILoginService;
import cn.gaozhong.basic.util.AjaxResult;
import cn.gaozhong.basic.util.HttpClientUtils;
import cn.gaozhong.basic.util.MD5Utils;
import cn.gaozhong.basic.util.StrUtils;
import cn.gaozhong.user.domain.LoginInfo;
import cn.gaozhong.user.domain.User;
import cn.gaozhong.user.domain.Wxuser;
import cn.gaozhong.user.mapper.LogininfoMapper;
import cn.gaozhong.user.mapper.UserMapper;
import cn.gaozhong.user.mapper.WxuserMapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     * 后台登录
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> account(LoginDto dto) {
        String username = dto.getUsername();
        String password = dto.getPassword();
        Integer type = dto.getType();
//        1、空校验
        if (StringUtils.isEmpty(username)
                ||StringUtils.isEmpty(password)
                ||StringUtils.isEmpty(type)){
            throw new CustomException("不能为空请重新填写");
        }
//        2、根据username+type查询logininfo  要查询username  phone email  三个字段
        LoginInfo loginInfo = logininfoMapper.loadByUsernameAndType(username,type);
//        2.1、查不到报错
        if (loginInfo==null){
            throw new CustomException("账户或密码错误请重新输入");
        }
        String salt = loginInfo.getSalt();
        String md5 = MD5Utils.encrypByMd5(password + salt);
//        2.2、查到了校验密码是否一致
        if (!md5.equals(loginInfo.getPassword())) {
//        3、密码错误，报错
            throw new CustomException("账户或密码错误请重新输入");
        }
//        4、登录成功
        String token = UUID.randomUUID().toString();
//        4.1、存储redis
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("loginInfo",loginInfo);
//        4.2、返回token+logininfo
        return map;

    }

    /**
     * 三方登录
     * @param dto
     * @return
     */
    @Override
    public AjaxResult wechat(WeChatDto dto) {
        String code = dto.getCode();
        if (StringUtils.isEmpty(code)){
            throw new CustomException("白干让老板扣你工资");
        }
//        1.通过code从微信获取token+openid
        String tokenUrl = BaseConstant.WeChatConstants.TOKEN_URL
                .replace("APPID", BaseConstant.WeChatConstants.APPID)
                .replace("SECRET", BaseConstant.WeChatConstants.SECRET)
                .replace("CODE", code);
        String tokenStr = HttpClientUtils.httpGet(tokenUrl);
        JSONObject tokenObj = JSONObject.parseObject(tokenStr);
        String accessToken = tokenObj.getString("access_token");
        String openId = tokenObj.getString("openid");
//        2.通过openid查询t_wxuser表，判断是否wxuser存在并且user_id不为空
        Wxuser wxuser = wxuserMapper.loadByOpenId(openId);
        if (wxuser !=null && wxuser.getUserId()!=null){
//        2.1 有，且userId存在，直接免密登录===第二次之后的扫码登录
            LoginInfo loginInfo = logininfoMapper.loadByUserId(wxuser.getUserId());
//        4、登录成功
            String token = UUID.randomUUID().toString();
//        4.1、存储redis
            redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
            Map<String, Object> map = new HashMap<>();
            map.put("token",token);
            loginInfo.setSalt(null);
            loginInfo.setPassword(null);
            map.put("loginInfo",loginInfo);
            return AjaxResult.me().setResultObj(map);
        }
//        2.2 没有，这里应该让浏览器跳转到绑定页面，让它自己输入账号和密码来完成绑定
//        返回token+openid
        String binderParams = "?accessToken="+accessToken+"&openId="+openId;
        return AjaxResult.me().setSuccess(false).setResultObj(binderParams);
    }

    @Override
    public Map<String, Object> binder(WeChatDto dto) {
        String phone = dto.getPhone();
        String password = dto.getPassword();
        String accessToken = dto.getAccessToken();
        String openId = dto.getOpenId();
        if (StringUtils.isEmpty(phone)
                ||StringUtils.isEmpty(password)
                ||StringUtils.isEmpty(accessToken)
                ||StringUtils.isEmpty(openId)){
            throw new CustomException("不能为空");
        }
//        1.根据username 查询t_user是否曾今已经存在
        User user = userMapper.loadByPhone(phone);
        LoginInfo loginInfo = null;
        if (user!=null){
//        1.1 存在 查询出来，等着绑定
            loginInfo = logininfoMapper.loadByUserId(user.getId());
        }else {
//        1.2 不存在 生成新的t_user + t_logininfo
            //保存数据将dto数据保存到user
            user = dto2User(dto);
            //保存数据将user数据保存到logininfo
            loginInfo = user2LoginInfo(user);
            //logininfo做新增
            logininfoMapper.save(loginInfo);
            //将logininfo的id赋值给user表的LogininfoId
            user.setLogininfoId(loginInfo.getId());
            //user做新增
            userMapper.save(user);
        }
//        2.根据token + openid 去微信查询微信的用户基本信息
        String wxuserUrl = BaseConstant.WeChatConstants.WXUSER_URL
                .replace("ACCESS_TOKEN",dto.getAccessToken())
                .replace("OPENID",dto.getOpenId());
        String wx = HttpClientUtils.httpGet(wxuserUrl);
//        3.根据微信的用户基本信息生成t_wxuser
        Wxuser wxuser = JSONObject.parseObject(wx, Wxuser.class);
//        4.t_wxuser绑定t_user
        wxuser.setUserId(user.getId());
        wxuserMapper.save(wxuser);
//        5.保存t_wxuser（完成了整个绑定流程）
        String token = UUID.randomUUID().toString();
//        4.1、存储redis
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        loginInfo.setSalt(null);
        loginInfo.setPassword(null);
        map.put("loginInfo",loginInfo);
        return map;
//        6.直接免密登录
    }
    private LoginInfo user2LoginInfo(User user) {
        LoginInfo logininfo = new LoginInfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        return logininfo;
    }

    private User dto2User(WeChatDto dto) {
        User user = new User();
        user.setUsername(dto.getPhone());
        user.setPhone(dto.getPhone());
        String salt = StrUtils.getComplexRandomString(32);
        String password = MD5Utils.encrypByMd5(dto.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(password);
        return user;
    }
}
